using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Reflection;
using System.Diagnostics;

namespace BrianLyttle.Samples.WinForms
{
    sealed internal class Diagnostics
    {
        /// <summary>
        /// Obtains a stack trace for the crash. Essential for understanding
        /// how a crash can be eliminated.
        /// </summary>
        /// <param name="Exception">Exeption object from the crash.</param>
        /// <returns></returns>
        internal static string GetStackTrace(Exception Exception)
        {
            //StringBuilder trace = new StringBuilder();
            StackTrace st = new StackTrace(Exception, true);

            //trace.AppendLine("Parsed Stack Trace:");
            //trace.AppendLine();

            //for (int i = 0; i < st.FrameCount; i++)
            //{
            //    StackFrame frame = st.GetFrame(i);
            //    trace.AppendLine(frame.GetMethod().Name + " (" +frame.GetFileName()+" "+ frame.GetFileLineNumber().ToString() + ")");
            //}

            //trace.AppendLine();
            //trace.AppendLine("Raw Stack Trace:");
            //trace.AppendLine();
            //trace.Append(st.ToString());

            return st.ToString();
        }


        //private static string EnhancedStackTrace(StackTrace objStackTrace, string strSkipClassName)
        //{
        //    int intFrame;
        //    System.Text.StringBuilder sb = new System.Text.StringBuilder();
        //    sb.Append(Environment.NewLine);
        //    sb.Append("---- Stack Trace ----");
        //    sb.Append(Environment.NewLine);
        //    for (int intFrame = 0; intFrame <= objStackTrace.FrameCount - 1; intFrame++)
        //    {
        //        StackFrame sf = objStackTrace.GetFrame(intFrame);
        //        MemberInfo mi = sf.GetMethod;
        //        if (strSkipClassName != "" && mi.DeclaringType.Name.IndexOf(strSkipClassName) > -1)
        //        {
        //        }
        //        else
        //        {
        //            sb.Append(StackFrameToString(sf));
        //        }
        //    }
        //    sb.Append(Environment.NewLine);
        //    return sb.ToString;
        //}

        //private static string StackFrameToString(StackFrame sf)
        //{
        //    System.Text.StringBuilder sb = new System.Text.StringBuilder();
        //    int intParam;
        //    MemberInfo mi = sf.GetMethod;
        //    sb.Append(" ");
        //    sb.Append(mi.DeclaringType.Namespace);
        //    sb.Append(".");
        //    sb.Append(mi.DeclaringType.Name);
        //    sb.Append(".");
        //    sb.Append(mi.Name);
        //    ParameterInfo[] objParameters = sf.GetMethod.GetParameters();
        //    ParameterInfo objParameter;
        //    sb.Append("(");
        //    intParam = 0;
        //    foreach (int objParameter in objParameters)
        //    {
        //        intParam += 1;
        //        if (intParam > 1)
        //        {
        //            sb.Append(", ");
        //        }
        //        sb.Append(objParameter.Name);
        //        sb.Append(" As ");
        //        sb.Append(objParameter.ParameterType.Name);
        //    }
        //    sb.Append(")");
        //    sb.Append(Environment.NewLine);
        //    sb.Append(" ");
        //    if (sf.GetFileName == null || sf.GetFileName.Length == 0)
        //    {
        //        sb.Append(System.IO.Path.GetFileName(ParentAssembly.CodeBase));
        //        sb.Append(": N ");
        //        sb.Append(string.Format("{0:#00000}", sf.GetNativeOffset));
        //    }
        //    else
        //    {
        //        sb.Append(System.IO.Path.GetFileName(sf.GetFileName));
        //        sb.Append(": line ");
        //        sb.Append(string.Format("{0:#0000}", sf.GetFileLineNumber));
        //        sb.Append(", col ");
        //        sb.Append(string.Format("{0:#00}", sf.GetFileColumnNumber));
        //        if (sf.GetILOffset != StackFrame.OFFSET_UNKNOWN)
        //        {
        //            sb.Append(", IL ");
        //            sb.Append(string.Format("{0:#0000}", sf.GetILOffset));
        //        }
        //    }
        //    sb.Append(Environment.NewLine);
        //    return sb.ToString;
        //}

        /// <summary>
        /// Gets the list of startup arguments passed to the application as a string. Good for
        /// debugging the application if you have special startup switches.
        /// </summary>
        /// <returns>String containing command-line arguments.</returns>
        internal static string GetStartupArguments()
        {
            string argsCombined = string.Empty;
            string[] args = Environment.GetCommandLineArgs();

            for (int i = 1; i < args.Length; i++)
            {
                argsCombined += (args[i] + " ");
            }

            return argsCombined;
        }

        /// <summary>
        /// Gets the current operating system version. Useful for
        /// reproducing errors if you have version dependent code
        /// in the application.
        /// </summary>
        /// <returns>String representing operating system version.</returns>
        internal static string GetOSVersion()
        {
            return Environment.OSVersion.VersionString;
        }

        /// <summary>
        /// Gets the number of logical processors available to the .NET framework. This
        /// is useful for debugging race conditions or other issues on SMP machines.
        /// </summary>
        /// <returns>String with count of processors.</returns>
        internal static string GetProcessorCount()
        {
            return Environment.ProcessorCount.ToString();
        }

        /// <summary>
        /// Get the number of bytes allocated to the working set of the application.
        /// Provides insight on memory allocation at time of crash.
        /// </summary>
        /// <returns>String reprenting number of bytes allocated for application.</returns>
        internal static string GetWorkingSet()
        {
            return Environment.WorkingSet.ToString() + " bytes";
        }

        /// <summary>
        /// Gets the path to the application. Useful if you have hard coded paths in an 
        /// application and need user to put application in a specific location.
        /// </summary>
        /// <returns>Path of executing assembly.</returns>
        internal static string GetAssemblyCodeBase()
        {
            return AppDomain.CurrentDomain.BaseDirectory +
                         AppDomain.CurrentDomain.FriendlyName;
        }

        /// <summary>
        /// Gets the time when the file was built. Useful if you have daily builds
        /// and want to study crash data over time.
        /// </summary>
        /// <returns>String containing timestamp of assembly.</returns>
        internal static DateTime GetAssemblyFileTime(Assembly Assembly)
        {
            DateTime buildDate;

            try
            {
                buildDate = File.GetLastWriteTime(Assembly.Location);
            }
            catch (Exception Ex)
            {
                buildDate = DateTime.MaxValue;
            }

            return buildDate;
        }
    }
}
